home *** CD-ROM | disk | FTP | other *** search
/ BBS in a Box 3 / BBS in a box - Trilogy III.iso / Files / Prog / D-G / GemsII / RealPixels / color.c next >
Encoding:
C/C++ Source or Header  |  1992-06-16  |  5.8 KB  |  280 lines  |  [TEXT/MPS ]

  1. /* Copyright (c) 1991 Regents of the University of California */
  2.  
  3. #ifndef lint
  4. static char SCCSid[] = "@(#)color.c 1.15 8/28/91 LBL";
  5. #endif
  6.  
  7. /*
  8.  *  color.c - routines for color calculations.
  9.  *
  10.  *     10/10/85
  11.  */
  12.  
  13. #include  <stdio.h>
  14.  
  15. #include  "color.h"
  16.  
  17. #define  MINELEN    8    /* minimum scanline length for encoding */
  18. #define  MINRUN        4    /* minimum run length */
  19.  
  20.  
  21. char *
  22. tempbuffer(len)            /* get a temporary buffer */
  23. unsigned  len;
  24. {
  25.     extern char  *malloc(), *realloc();
  26.     static char  *tempbuf = NULL;
  27.     static int  tempbuflen = 0;
  28.  
  29.     if (len > tempbuflen) {
  30.         if (tempbuflen > 0)
  31.             tempbuf = realloc(tempbuf, len);
  32.         else
  33.             tempbuf = malloc(len);
  34.         tempbuflen = tempbuf==NULL ? 0 : len;
  35.     }
  36.     return(tempbuf);
  37. }
  38.  
  39.  
  40. fwritecolrs(scanline, len, fp)        /* write out a colr scanline */
  41. register COLR  *scanline;
  42. int  len;
  43. register FILE  *fp;
  44. {
  45.     register int  i, j, beg, cnt;
  46.     int  c2;
  47.     
  48.     if (len < MINELEN)        /* too small to encode */
  49.         return(fwrite((char *)scanline,sizeof(COLR),len,fp) - len);
  50.     if (len > 32767)        /* too big! */
  51.         return(-1);
  52.     putc(2, fp);            /* put magic header */
  53.     putc(2, fp);
  54.     putc(len>>8, fp);
  55.     putc(len&255, fp);
  56.                     /* put components seperately */
  57.     for (i = 0; i < 4; i++) {
  58.         for (j = 0; j < len; j += cnt) {    /* find next run */
  59.         for (beg = j; beg < len; beg += cnt) {
  60.             for (cnt = 1; cnt < 127 && beg+cnt < len &&
  61.                 scanline[beg+cnt][i] == scanline[beg][i]; cnt++)
  62.             ;
  63.             if (cnt >= MINRUN)
  64.             break;            /* long enough */
  65.         }
  66.         if (beg-j > 1 && beg-j < MINRUN) {
  67.             c2 = j+1;
  68.             while (scanline[c2++][i] == scanline[j][i])
  69.             if (c2 == beg) {    /* short run */
  70.                 putc(128+beg-j, fp);
  71.                 putc(scanline[j][i], fp);
  72.                 j = beg;
  73.                 break;
  74.             }
  75.         }
  76.         while (j < beg) {        /* write out non-run */
  77.             if ((c2 = beg-j) > 128) c2 = 128;
  78.             putc(c2, fp);
  79.             while (c2--)
  80.             putc(scanline[j++][i], fp);
  81.         }
  82.         if (cnt >= MINRUN) {        /* write out run */
  83.             putc(128+cnt, fp);
  84.             putc(scanline[beg][i], fp);
  85.         } else
  86.             cnt = 0;
  87.         }
  88.     }
  89.     return(ferror(fp) ? -1 : 0);
  90. }
  91.  
  92.  
  93. freadcolrs(scanline, len, fp)        /* read in an encoded colr scanline */
  94. register COLR  *scanline;
  95. int  len;
  96. register FILE  *fp;
  97. {
  98.     register int  i, j;
  99.     int  code;
  100.                     /* determine scanline type */
  101.     if (len < MINELEN)
  102.         return(oldreadcolrs(scanline, len, fp));
  103.     if ((i = getc(fp)) == EOF)
  104.         return(-1);
  105.     if (i != 2) {
  106.         ungetc(i, fp);
  107.         return(oldreadcolrs(scanline, len, fp));
  108.     }
  109.     scanline[0][GRN] = getc(fp);
  110.     scanline[0][BLU] = getc(fp);
  111.     if ((i = getc(fp)) == EOF)
  112.         return(-1);
  113.     if (scanline[0][GRN] != 2 || scanline[0][BLU] & 128) {
  114.         scanline[0][RED] = 2;
  115.         scanline[0][EXP] = i;
  116.         return(oldreadcolrs(scanline+1, len-1, fp));
  117.     }
  118.     if ((scanline[0][BLU]<<8 | i) != len)
  119.         return(-1);        /* length mismatch! */
  120.                     /* read each component */
  121.     for (i = 0; i < 4; i++)
  122.         for (j = 0; j < len; ) {
  123.         if ((code = getc(fp)) == EOF)
  124.             return(-1);
  125.         if (code > 128) {    /* run */
  126.             scanline[j++][i] = getc(fp);
  127.             for (code &= 127; --code; j++)
  128.             scanline[j][i] = scanline[j-1][i];
  129.         } else            /* non-run */
  130.             while (code--)
  131.             scanline[j++][i] = getc(fp);
  132.         }
  133.     return(feof(fp) ? -1 : 0);
  134. }
  135.  
  136.  
  137. oldreadcolrs(scanline, len, fp)        /* read in an old colr scanline */
  138. register COLR  *scanline;
  139. int  len;
  140. register FILE  *fp;
  141. {
  142.     int  rshift;
  143.     register int  i;
  144.     
  145.     rshift = 0;
  146.     
  147.     while (len > 0) {
  148.         scanline[0][RED] = getc(fp);
  149.         scanline[0][GRN] = getc(fp);
  150.         scanline[0][BLU] = getc(fp);
  151.         scanline[0][EXP] = getc(fp);
  152.         if (feof(fp) || ferror(fp))
  153.             return(-1);
  154.         if (scanline[0][RED] == 1 &&
  155.                 scanline[0][GRN] == 1 &&
  156.                 scanline[0][BLU] == 1) {
  157.             for (i = scanline[0][EXP] << rshift; i > 0; i--) {
  158.                 copycolr(scanline[0], scanline[-1]);
  159.                 scanline++;
  160.                 len--;
  161.             }
  162.             rshift += 8;
  163.         } else {
  164.             scanline++;
  165.             len--;
  166.             rshift = 0;
  167.         }
  168.     }
  169.     return(0);
  170. }
  171.  
  172.  
  173. fwritescan(scanline, len, fp)        /* write out a scanline */
  174. register COLOR  *scanline;
  175. int  len;
  176. FILE  *fp;
  177. {
  178.     COLR  *clrscan;
  179.     int  n;
  180.     register COLR  *sp;
  181.                     /* get scanline buffer */
  182.     if ((sp = (COLR *)tempbuffer(len*sizeof(COLR))) == NULL)
  183.         return(-1);
  184.     clrscan = sp;
  185.                     /* convert scanline */
  186.     n = len;
  187.     while (n-- > 0) {
  188.         setcolr(sp[0], scanline[0][RED],
  189.                   scanline[0][GRN],
  190.                   scanline[0][BLU]);
  191.         scanline++;
  192.         sp++;
  193.     }
  194.     return(fwritecolrs(clrscan, len, fp));
  195. }
  196.  
  197.  
  198. freadscan(scanline, len, fp)        /* read in a scanline */
  199. register COLOR  *scanline;
  200. int  len;
  201. FILE  *fp;
  202. {
  203.     register COLR  *clrscan;
  204.  
  205.     if ((clrscan = (COLR *)tempbuffer(len*sizeof(COLR))) == NULL)
  206.         return(-1);
  207.     if (freadcolrs(clrscan, len, fp) < 0)
  208.         return(-1);
  209.                     /* convert scanline */
  210.     colr_color(scanline[0], clrscan[0]);
  211.     while (--len > 0) {
  212.         scanline++; clrscan++;
  213.         if (clrscan[0][RED] == clrscan[-1][RED] &&
  214.                 clrscan[0][GRN] == clrscan[-1][GRN] &&
  215.                 clrscan[0][BLU] == clrscan[-1][BLU] &&
  216.                 clrscan[0][EXP] == clrscan[-1][EXP])
  217.             copycolor(scanline[0], scanline[-1]);
  218.         else
  219.             colr_color(scanline[0], clrscan[0]);
  220.     }
  221.     return(0);
  222. }
  223.  
  224.  
  225. setcolr(clr, r, g, b)        /* assign a short color value */
  226. register COLR  clr;
  227. double  r, g, b;
  228. {
  229.     double  frexp();
  230.     double  d;
  231.     int  e;
  232.     
  233.     d = r > g ? r : g;
  234.     if (b > d) d = b;
  235.  
  236.     if (d <= 1e-32) {
  237.         clr[RED] = clr[GRN] = clr[BLU] = 0;
  238.         clr[EXP] = 0;
  239.         return;
  240.     }
  241.  
  242.     d = frexp(d, &e) * 256.0 / d;
  243.  
  244.     clr[RED] = r * d;
  245.     clr[GRN] = g * d;
  246.     clr[BLU] = b * d;
  247.     clr[EXP] = e + COLXS;
  248. }
  249.  
  250.  
  251. colr_color(col, clr)        /* convert short to float color */
  252. register COLOR  col;
  253. register COLR  clr;
  254. {
  255.     double  f;
  256.     
  257.     if (clr[EXP] == 0)
  258.         col[RED] = col[GRN] = col[BLU] = 0.0;
  259.     else {
  260.         f = ldexp(1.0, (int)clr[EXP]-(COLXS+8));
  261.         col[RED] = (clr[RED] + 0.5)*f;
  262.         col[GRN] = (clr[GRN] + 0.5)*f;
  263.         col[BLU] = (clr[BLU] + 0.5)*f;
  264.     }
  265. }
  266.  
  267.  
  268. bigdiff(c1, c2, md)            /* c1 delta c2 > md? */
  269. register COLOR  c1, c2;
  270. double  md;
  271. {
  272.     register int  i;
  273.  
  274.     for (i = 0; i < 3; i++)
  275.         if (colval(c1,i)-colval(c2,i) > md*colval(c2,i) ||
  276.             colval(c2,i)-colval(c1,i) > md*colval(c1,i))
  277.             return(1);
  278.     return(0);
  279. }
  280.